package stock;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet; 
import org.apache.poi.ss.util.CellRangeAddress;
import org.hibernate.type.DateType;
import org.hibernate.type.DoubleType;
import org.hibernate.type.FloatType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.LongType;
import org.hibernate.type.ShortType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;

import jxl.Workbook;
import jxl.WorkbookSettings;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * 数据导出为Excel
 * 
 * 导入excel文件model 的field数据
 * 类型：String,int,Integer,double,Double,Float,float,short,Short,char,char[]
 * 
 */
@SuppressWarnings("all")
public class ExportExcel {

	public static List<?> parseCsv(File f, Class<?> claz) {
		List<Object> result = new ArrayList<>();

		BufferedReader bufferedReader = null;
		InputStreamReader fileReader = null;
		FileInputStream fileInputStream = null;

		try {
			fileInputStream = new FileInputStream(f); 
			fileReader = new InputStreamReader(fileInputStream,"GBK");
			bufferedReader = new BufferedReader(fileReader);
			List<importExcel> methods = getCSVObject(claz, bufferedReader.readLine());
			String line = null;
			while ((line = bufferedReader.readLine()) != null) {
				String item[] = line.split(",");// CSV格式文件为逗号分隔符文件，这里根据逗号切分
				Object ob = claz.newInstance();
				/*
				 * for (int i = 0;i < item.length;i++) { invokeObject(item[i], methods.get(i),
				 * ob); }
				 */
				for (int i = 0; i < methods.size(); i++) {
					invokeObject(item[i], methods.get(i), ob);
				}
				result.add(ob);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			if (bufferedReader != null) {
				try {
					bufferedReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (fileReader != null) {
				try {
					fileReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (fileInputStream != null) {
				try {
					fileInputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		return result;
	}

	private static List<importExcel> getCSVObject(Class<?> claz, String titles) {
		List<importExcel> list = ExportExcel.getImportClassField(claz);
		List<String> titleList = Arrays.asList(titles.split(","));
		List<importExcel> result = new ArrayList<>();

		for (String title : titleList) {
			for (importExcel importCsv : list) {
				if (title.trim().toLowerCase().equals(importCsv.getDesc().trim().toLowerCase())) {
					result.add(importCsv);
				}
			}
		}
		return result;
	}

	private static void invokeObject(String cellStr, importExcel importExcel, Object ob)
			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		Class<?>[] claz = importExcel.getClaz();
		List<Object> params = new ArrayList<>();

		for (Class<?> cl : claz) {
			paramType(cl.getName(), cellStr, params);
		}

		Method method = importExcel.getMethod();
		method.invoke(ob, params.toArray());

	}

	private static void paramType(String claz, String cellStr, List<Object> params) {
		if (claz.equals(String.class.getName())) {
			params.add(cellStr);
		} else if (claz.equals(Integer.class.getName())) {
			params.add(Integer.valueOf(cellStr));
		} else if (claz.equals(int.class.getName())) {
			params.add((int) Integer.parseInt(cellStr));
		} else if (claz.equals(Float.class.getName())) {
			if (cellStr.equals("None") || cellStr == null) {
				params.add(0f);
			} else {
				params.add(Float.valueOf(cellStr));
			}

		} else if (claz.equals(float.class.getName())) {
			params.add((float) Float.parseFloat(cellStr));
		} else if (claz.equals(Double.class.getName())) {
			params.add(Double.valueOf(cellStr));
		} else if (claz.equals(double.class.getName())) {
			params.add((double) Double.parseDouble(cellStr));
		} else if (claz.equals(long.class.getName())) {
			params.add((long) Long.parseLong(cellStr));
		} else if (claz.equals(Long.class.getName())) {
			params.add(Long.valueOf(cellStr));
		} else if (claz.equals(char.class.getName())) {
			params.add(cellStr.toCharArray()[0]);
		} else if (claz.equals(char[].class.getName())) {
			params.add(cellStr.toCharArray());
		} else if (claz.equals(Short.class.getName())) {
			params.add(Short.valueOf(cellStr));
		} else if (claz.equals(short.class.getName())) {
			params.add((short) Short.parseShort(cellStr));
		}
	}

	private static String getSetMethodName(String fieldName) {
		StringBuffer sb = new StringBuffer();
		sb.append("set");
		char[] charr = fieldName.toCharArray();
		if (charr.length <= 1) {
			return fieldName.toUpperCase();
		}
		if (Character.isLowerCase(charr[1])) {
			sb.append(fieldName.substring(0, 1).toUpperCase());
			sb.append(fieldName.substring(1));
		} else {
			sb.append(fieldName.substring(0, 1));
			sb.append(fieldName.substring(1));
		}
		return sb.toString();
	}

	private static List<importExcel> sortExcelSheetTitle(Row row, Class<?> claz) {
		List<importExcel> list = ExportExcel.getImportClassField(claz);
		List<importExcel> result = new ArrayList<>();

		if (row == null || list == null || list.size() <= 0) {
			return null;
		}

		String excelTitles = "";
		String modelTitles = "";

		for (int i = 0; i < row.getLastCellNum(); i++) {
			String cellStr = getCellStr(row.getCell(i));
			excelTitles += cellStr;
			for (importExcel model : list) {
				if (i == 0) {
					modelTitles += model.getDesc();
				}
				if (model.getDesc().equals(cellStr)) {
					result.add(model);
				}
			}
		}

		if ("".equals(modelTitles) || "".equals(excelTitles) || !excelTitles.equals(modelTitles)) {
			return null;
		}

		return result;
	}

	private static String getCellStr(Cell cell) {
		String result = "";
		DataFormatter dataFormatter = new DataFormatter();
		result = dataFormatter.formatCellValue(cell);
		return result;
	}

	private static List<importExcel> getImportClassField(Class<?> claz) {
		List<Field> list = new ArrayList<>();
		list.addAll(Arrays.asList(claz.getFields()));
		List<importExcel> sortList = new ArrayList<>();
		Map<String, importExcel> map = getClassSetMethod(claz);

		for (Field field : list) {
			Excel exportFile = field.getAnnotation(Excel.class);
			if (exportFile != null && exportFile.isModel()) {
				String methodName = getSetMethodName(field.getName());
				if (map.keySet().contains(methodName)) {
					importExcel importExcel = map.get(methodName);
					importExcel.setDesc(exportFile.desc());
					sortList.add(importExcel);
				}
			}
		}
		return sortList;
	}

	private static List<exportSort> getExportClassSortFiled(Class<?> claz) {

		List<Field> list = new ArrayList<>();
		exportSort exportSort = null;
		List<String> vaList = null;
		List<String> desList = null;
		String val = "";
		String desc = "";
		list.addAll(Arrays.asList(claz.getDeclaredFields()));
		list.addAll(Arrays.asList(claz.getFields()));
		List<exportSort> sortList = new ArrayList<>();

		for (Field field : list) {
			Excel exportFile = field.getAnnotation(Excel.class);
			if (exportFile != null && exportFile.isExport()) {
				if (ObjType.OUT_KEY.equals(exportFile.type())) {
					vaList = new ArrayList<>();
					desList = new ArrayList<>();
					val = exportFile.val();
					if (val.contains(",")) {
						vaList = Arrays.asList(val.split(","));
					} else {
						vaList.add(val);
					}
					desc = exportFile.desc();
					if (desc.contains(",")) {
						desList = Arrays.asList(desc.split(","));
					} else {
						desList.add(desc);
					}
					for (int j = 0; j < vaList.size(); j++) {
						exportSort = new exportSort();
						exportSort.setDesc(desList.get(j));
						exportSort.setMethod(getGetMethod(claz, field.getName()));
						exportSort.setType(exportFile.type());
						exportSort.setVal(vaList.get(j));
						sortList.add(exportSort);
					}
				} else {
					exportSort = new exportSort();
					exportSort.setDesc(exportFile.desc());
					exportSort.setMethod(getGetMethod(claz, field.getName()));
					exportSort.setPath(exportFile.path());
					exportSort.setType(exportFile.type());
					exportSort.setVal(exportFile.val());
					sortList.add(exportSort);
				}
			}
		}
		return sortList;

	}

	private static Method getGetMethod(Class objectClass, String fieldName) {
		StringBuffer sb = new StringBuffer();
		sb.append("get");
		sb.append(fieldName.substring(0, 1).toUpperCase());
		sb.append(fieldName.substring(1));
		try {
			return objectClass.getMethod(sb.toString());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static List<String> getModelExcelClassFieldDesc(Class<?> claz) {

		List<Field> list = new ArrayList<>();

		list.addAll(Arrays.asList(claz.getDeclaredFields()));
		list.addAll(Arrays.asList(claz.getFields()));
		List<String> result = new ArrayList<>();

		for (Field field : list) {
			Excel exportFile = field.getAnnotation(Excel.class);
			if (exportFile != null && exportFile.isModel()) {
				result.add(exportFile.desc());
			}
		}
		return result;

	}

	/*
	 * private static List<exportSort> sortExport(List<exportSort> sortList,
	 * Class<?> claz) { ExportFileSort fileSort =
	 * claz.getAnnotation(ExportFileSort.class); boolean sort = true; if (fileSort
	 * != null) { sort = fileSort.sort(); } exportSort[] es = sortList.toArray(new
	 * exportSort[0]);
	 * 
	 * if (sort) { Arrays.sort(es, new Comparator<exportSort>() {
	 * 
	 * @Override public int compare(exportSort o1, exportSort o2) { // TODO
	 * Auto-generated method stub if (o1.getSort() > o2.getSort()) { return 1; }
	 * else if (o1.getSort() == o2.getSort()) { return 0; } return -1; }
	 * 
	 * }); } else { Arrays.sort(es, new Comparator<exportSort>() {
	 * 
	 * @Override public int compare(exportSort o1, exportSort o2) { // TODO
	 * Auto-generated method stub if (o1.getSort() > o2.getSort()) { return -1; }
	 * else if (o1.getSort() == o2.getSort()) { return 0; } return 1; }
	 * 
	 * }); }
	 * 
	 * return Arrays.asList(es); }
	 */
	/**
	 * @param claz
	 */
	private static Map<String, importExcel> getClassSetMethod(Class<?> claz) {
		Method[] ms = claz.getMethods();
		Map<String, importExcel> map = new HashMap();
		importExcel importExcel = null;
		for (Method method : ms) {
			importExcel = new importExcel();
			importExcel.setMethod(method);
			importExcel.setClaz(method.getParameterTypes());
			map.put(method.getName(), importExcel);
		}
		return map;
	}

	public static void main(String[] args) {

	}
}

class importExcel {
	private Method method;

	private String desc;

	private Class<?>[] claz;

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public Class<?>[] getClaz() {
		return claz;
	}

	public void setClaz(Class<?>[] claz) {
		this.claz = claz;
	}

}

class exportSort {
	private Method method;

	private String desc;

	private int sort;

	private String type;

	private String path;

	private String val;

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public int getSort() {
		return sort;
	}

	public void setSort(int sort) {
		this.sort = sort;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getVal() {
		return val;
	}

	public void setVal(String val) {
		this.val = val;
	}

	public static void main(String[] args) throws IOException {
		String zipFile = "C:\\uploadImg\\uploadFiles\\2018-09-15\\a3731d6f240645e7982bcd90127657de.zip";
		String sourceFile = "C:\\uploadImg\\uploadFiles\\2018-09-15\\a3731d6f240645e7982bcd90127657de.txt";
		File zipFiles = new File(zipFile);
		if (zipFiles.exists()) {
			zipFiles.delete();
		}
		ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFiles));
		zipOut.putNextEntry(new ZipEntry("a3731d6f240645e7982bcd90127657de.txt"));
		FileInputStream fileIn = new FileInputStream(new File(sourceFile));
		int len;
		byte[] b = new byte[1024];
		while ((len = fileIn.read(b)) > 0) {
			System.out.println("-------------------------------");
			System.out.println(len);
			zipOut.write(b, 0, len);
		}
		zipOut.closeEntry();
		zipOut.close();
		fileIn.close();
	}

}
